package comm

import (
	"com.wangzhumo.lottery/conf"
	"com.wangzhumo.lottery/models"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/url"
	"strconv"
)

const CookieKey = "lottery_c"

// ClientIp 通过Request 获取用户的IP
func ClientIp(request *http.Request) string {
	host, _, _ := net.SplitHostPort(request.RemoteAddr)
	return host
}

// Redirect 跳转到
func Redirect(write http.ResponseWriter, url string) {
	write.Header().Add("Location", url)
	write.WriteHeader(http.StatusFound)
}

// GetLoginUser 通过Cookie获取用户的信息
func GetLoginUser(request *http.Request) *models.ObjLoginUser {
	cookie, err := request.Cookie(CookieKey)
	if err != nil {
		return nil
	}
	parseQuery, err := url.ParseQuery(cookie.Value)
	if err != nil {
		return nil
	}

	// 验证值- UID
	uid, err := strconv.Atoi(parseQuery.Get("uid"))
	if err != nil || uid < 1 {
		return nil
	}

	// 验证值- time
	now, err := strconv.Atoi(parseQuery.Get("now"))
	// time是否逾期
	if err != nil || (NowUnix()-now) > 86400*30 {
		return nil
	}

	// 用户有效
	objLoginUser := &models.ObjLoginUser{
		UID:      uid,
		Username: parseQuery.Get("username"),
		Now:      now,
		Ip:       ClientIp(request),
		Sign:     parseQuery.Get("sign"),
	}
	sign := VerifySign(objLoginUser)
	if !sign {
		log.Println("sign check error.", objLoginUser)
		return nil
	}
	return objLoginUser
}

// SetLoginUser 设置用户到Cookie
func SetLoginUser(writer http.ResponseWriter, user *models.ObjLoginUser) {
	if user == nil || user.UID < 1 {
		c := &http.Cookie{
			Name:   CookieKey,
			Value:  "",
			Path:   "/",
			MaxAge: -1,
		}
		http.SetCookie(writer, c)
		return
	}
	// 否则签名
	if user.Sign == "" {
		user.Sign = Sign(user)
	}
	params := url.Values{}
	params.Add("uid", strconv.Itoa(user.UID))
	params.Add("username", user.Username)
	params.Add("now", strconv.Itoa(user.Now))
	params.Add("ip", user.Ip)
	params.Add("sign", user.Sign)

	c := &http.Cookie{
		Name:   CookieKey,
		Value:  params.Encode(),
		Path:   "/",
		MaxAge: 30 * 86400,
	}
	http.SetCookie(writer, c)
}

// Sign 创建签名
func Sign(user *models.ObjLoginUser) string {
	signStr := fmt.Sprintf("uid=%d&username=%s&secret=%s&now=%d",
		user.UID, user.Username, conf.CookieSecret, user.Now)
	return CreateSign(signStr)
}

// VerifySign 验证签名
func VerifySign(user *models.ObjLoginUser) bool {
	serverSign := Sign(user)
	return serverSign == user.Sign
}
